home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_01_03
/
1n03073a
< prev
next >
Wrap
Text File
|
1990-07-08
|
16KB
|
675 lines
/*
Screen
2.50
19-Jun-1990
ANSI C for MS-DOS w/monochrome or color text
display
Provides a set of functions for manipulating a
text display. To drastically improve the speed
of this module, NO RANGE CHECKING is done!
Invalid line/column values may cause portions
of non-video memory to be corrupted!
Written by Scott Robert Ladd. Released into
the public domain.
*/
#include "conio.h"
#include "dos.h"
#include "screen.h"
#include "stdarg.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
static ScrType VideoType = ST_UNKNOWN;
static ScrMode VideoMode = SM_UNKNOWN;
static ScrMode OriginalMode = SM_UNKNOWN;
static ScrAccess AccessMode = SA_DIRECT;
static unsigned int Width = 0;
static unsigned int Length = 0;
static unsigned int BaseAdr = 0;
static unsigned int CursorShape = 0;
static int CursorHidden = 0;
static int * SavedScreen = NULL;
static unsigned int SavedCursPos = 0;
static int SavedCursShp = 0;
static union REGS regs;
#if !defined(MK_FP)
#define MK_FP(seg,off) (void far *)(((long)/
(seg) << 16L) | (long)(off))
#endif
ScrType ScrOpen(void)
{
int i, status_changed;
unsigned char orig_status;
int far * vmemptr;
/* Attempt to identify the type of video adapter installed.
Call VGA "Identify Adapter Service" first */
regs.h.ah = 0x1A;
regs.h.al = 0;
int86(0x10,®s,®s);
if (regs.h.al == 0x1A)
{
switch (regs.h.bl)
{
case 1 :
VideoType = ST_MDA;
break;
case 2 :
VideoType = ST_CGA;
break;
case 4 :
case 5 :
VideoType = ST_EGA;
break;
case 7 :
case 8 :
VideoType = ST_VGA;
break;
case 10:
case 11:
case 12:
VideoType = ST_MCGA;
break;
default:
return 1;
}
}
else
{
/* VGA services not available -- maybe it's EGA */
regs.h.ah = 0x12;
regs.x.bx = 0x0010;
int86(0x10,®s,®s);
/* if BX is 0x10, we have an EGA */
if (regs.x.bx != 0x10)
VideoType = ST_EGA;
else
{
/* check two-bit "monitor type" setting in equipment word */
int86(0x11,®s,®s);
switch ((regs.h.al & 0x30) >> 4)
{
case 0 :
return 1;
case 1 :
case 2 :
VideoType = ST_CGA;
break;
case 3 :
/* if we have a mono adapter, a Hercules can be
differentiated from an MDA by seeing if the high bit
of the status register changes */
status_changed = 0;
orig_status = (unsigned char)(inp(0x03BA) & 0x80);
for (i=0; (i<30000) && (!status_changed); ++i)
if (orig_status != (unsigned char)/
(inp(0x03BA) & 0x80))
status_changed = 1;
if (status_changed)
VideoType = ST_HGC;
else
VideoType = ST_MDA;
}
}
}
/* store the segment of video memory */
if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
BaseAdr = 0xB000;
else
BaseAdr = 0xB800;
/* save the original cursor shape */
regs.h.ah = 3;
regs.h.bh = 0;
int86(0x10,®s,®s);
SavedCursShp = regs.x.cx;
/* and the orihginal cursor position */
regs.h.ah = 3;
regs.h.bh = 0;
int86(0x10,®s,®s);
SavedCursPos = regs.x.dx;
/* find width of the orginal screen */
regs.h.ah = 0x0F;
int86(0x10,®s,®s);
Width = (int) regs.h.ah;
/* find length of the original screen */
regs.x.ax = 0x1130;
regs.h.bh = 0;
regs.x.dx = 0;
int86(0x10,®s,®s);
Length = regs.x.dx + 1;
if (Length == 1)
Length = 25;
/* now, allocate a buffer to hold the original
screen contents... */
SavedScreen = malloc(Length * Width * 2);
/* ...and save the original screen */
if (SavedScreen != NULL)
for (i = 0; i < Length * Width; i++)
{
vmemptr = MK_FP(BaseAdr,i << 1);
SavedScreen[i] = *vmemptr;
}
/* make note of the original screen mode */
switch (Width)
{
case 40:
OriginalMode = SM_25x40;
break;
case 80:
switch (Length)
{
case 25:
OriginalMode = SM_25x80;
break;
case 30:
OriginalMode = SM_30x80;
break;
case 43:
OriginalMode = SM_43x80;
break;
case 50:
OriginalMode = SM_50x80;
}
}
/* if we have an identifiable screen mode, make it
the current mode */
if (OriginalMode != -1)
VideoMode = OriginalMode;
/* mark the cursor as visible */
CursorHidden = 0;
/* get outa here */
return VideoType;
}
void ScrClose()
{
int i;
int far * vmemptr;
/* reset to orginal mode */
if ((OriginalMode != VideoMode) &&/
(OriginalMode != SM_UNKNOWN))
ScrSetMode(OriginalMode);
/* restore original screen contents */
if (SavedScreen != NULL)
for (i = 0; i < Length * Width; i++)
{
vmemptr = MK_FP(BaseAdr,i << 1);
*vmemptr = SavedScreen[i];
}
/* restore original cursor shape */
regs.h.ah = 1;
regs.x.cx = SavedCursShp;
int86(0x10,®s,®s);
/* restore original cursor position */
regs.h.ah = 2;
regs.h.bh = 0;
regs.x.dx = SavedCursPos;
int86(0x10,®s,®s);
}
int ScrSetMode(ScrMode mode)
{
/* don't change to the current mode */
if (VideoMode == mode)
return 1;
/* if we don't know the type of screen we have,
don't change mode */
if (OriginalMode == SM_UNKNOWN)
return 1;
/* make sure the mode requested is valid */
if ((mode < SM_25x40) || (mode > SM_50x80))
return 0;
/* set modes */
switch (mode)
{
case SM_25x40:
if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
return 0;
else
{
regs.x.ax = 0x0001;
int86(0x10,®s,®s);
Length = 25;
Width = 40;
}
break;
case SM_25x80:
if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
{
regs.x.ax = 0x0007;
int86(0x10,®s,®s);
}
else /* color */
{
regs.x.ax = 0x0003;
int86(0x10,®s,®s);
switch (VideoType)
{
case ST_CGA:
regs.x.ax = 0x1112;
int86(0x10,®s,®s);
break;
case ST_EGA:
regs.x.ax = 0x1111;
int86(0x10,®s,®s);
break;
case ST_VGA:
regs.x.ax = 0x1114;